package com.sneakxy.mybatis.commons.config;

import java.util.List;

import javax.sql.DataSource;
import javax.sql.XADataSource;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.transaction.SpringManagedTransactionFactory;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.Resource;

import com.sneakxy.mybatis.commons.properties.SpringDataMybatisProperties;
import com.sneakxy.mybatis.commons.repository.config.MybatisSqlSessionFactoryBean;
import com.sneakxy.mybatis.commons.utils.SnowflakeIdGenerator;
import com.sneakxy.mybatis.commons.utils.SnowflakeIdGeneratorImpl;

@AutoConfiguration
@ConditionalOnClass({ DataSource.class, XADataSource.class })
@EnableConfigurationProperties(SpringDataMybatisProperties.class)
@ConditionalOnProperty(prefix = SpringDataMybatisProperties.CONFIG_PREFIX, value = "enable", havingValue = "true", matchIfMissing = true)
public class SpringDataMybatisAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean(SqlSessionFactory.class)
	@ConfigurationProperties(prefix = SpringDataMybatisProperties.CONFIG_PREFIX)
	public SqlSessionFactoryBean sqlSessionFactory(
			List<SqlSessionFactoryConfiguer> configurs, 
			DataSource dataSource, 
			SnowflakeIdGenerator snowflakeIdGenerator, 
			SpringDataMybatisProperties springDataMybatisProperties) {
		MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
		factory.setDataSource(dataSource);
		factory.setTransactionFactory(new SpringManagedTransactionFactory());
		factory.setSpringDataMybatisProperties(springDataMybatisProperties);
		factory.setSqlSessionFactoryConfiguers(configurs);
		factory.setSnowflakeIdGenerator(snowflakeIdGenerator);
		Resource[] resources = springDataMybatisProperties.resolveMapperLocations();
		if(!ObjectUtils.isEmpty(resources)) {
			factory.setMapperLocations(resources);
		}
		return factory;
	}
	
	@Bean
	@ConditionalOnMissingBean(SnowflakeIdGenerator.class)
	public SnowflakeIdGenerator snowflakeIdGenerator(SpringDataMybatisProperties springDataMybatisProperties) {
		return new SnowflakeIdGeneratorImpl(
				springDataMybatisProperties.getSnowflake().getEpoch(), 
				springDataMybatisProperties.getSnowflake().getWorkIdBits(), 
				springDataMybatisProperties.getSnowflake().getWorkId());
	}
	
}
